import config from './config'
import page from './page'
import storage from './storage'
import http from './http'
import crypto from './crypto'
import api from './api'
import env from './env'
import update from './update'

import * as tool from './tool'
import * as dialog from './dialog'
import * as wechat from './wechat'
import * as runtime from './runtime'
import * as form from './form'
import * as auth from './auth'
import * as oss from './oss/index'
import * as hook from './hook'

export const qly = {
    env,
    config,
    tool,
    dialog,
    wechat,
    runtime,
    page,
    http,
    storage,
    form,
    crypto,
    api,
    update,
    auth,
    oss,
    hook,
}

export default {
    install(Vue) {
        
        // 挂载全局对象
        Vue.config.globalProperties.qly = qly
        
        // 处理本地地址
        const replaceHost = (url, origin) => {
            const protocols = ['http://', 'https://']
            for (const protocol of protocols) {
                const remoteOrigin = protocol + __DEV_REMOTE_IP__
                if (url.startsWith(origin)) {
                    return remoteOrigin + url.substring(origin.length)
                }
            }
            return url
        }
        env.baseUrl = replaceHost(env.baseUrl, 'http://localhost')
        env.baseUrl = replaceHost(env.baseUrl, 'http://127.0.0.1')
        
        // 处理h5跨域
        // #ifdef H5
        const envUrl = new URL(env.baseUrl)
        if (envUrl.origin !== window.origin) {
            env.baseUrl = env.baseUrl.replace(envUrl.origin, window.origin)
        }
        // #endif
        
        // 处理$once重复注册问题
        const once = {}
        const uni$once = uni.$once
        uni.$once = (eventName, callback) => {
            if (once[eventName]) {
                uni.$off(eventName, once[eventName])
                delete once[eventName]
            }
            once[eventName] = callback
            return uni$once(eventName, callback)
        }
        
        // 处理h5支付
        // #ifdef H5
        const parser = new DOMParser()
        const providerHandler = {
            alipay: options => {
                uni.showLoading({
                    title: '支付中...',
                })
                const vDocument = parser.parseFromString(options.orderInfo, 'text/html')
                const form = vDocument.getElementsByTagName('form')[0]
                form.target = '_blank'
                document.body.appendChild(form)
                uni.$once('onAppShow', () => {
                    uni.hideLoading()
                    options.success && options.success()
                })
                form.submit()
                form.remove()
            }
        }
        uni.requestPayment = options => {
            const handler = providerHandler[options.provider]
            if (handler == null) {
                options.fail && options.fail({
                    errMsg: '支付方式不支持'
                })
            } else {
                handler(options)
            }
        }
        // #endif
        
        // 处理h5保存图片
        // #ifdef H5
        uni.saveImageToPhotosAlbum = options => {
            const element = document.createElement("a")
            element.download = options.fileName || new Date().getTime() + '.png'
            element.href = options.filePath
            document.body.appendChild(element)
            element.click()
            element.remove()
            options.success && options.success({
                path: null
            })
        }
        // #endif
        
        // 处理h5录音
        // #ifdef H5
        const recorderManager = {
            _mediaStream: null,
            _mediaRecorder: null,
            _audioChunks: [],
            _callbacks: {
                start: [],
                stop: [],
                pause: [],
                error: []
            },
            
            // 开始录音
            async start(options = {}) {
                try {
                    this._mediaStream = await navigator.mediaDevices.getUserMedia({
                        audio: {
                            sampleRate: options.sampleRate || 16000, // 采样率
                            channelCount: options.numberOfChannels || 1   // 声道数
                        }
                    })
                    
                    this._mediaRecorder = new MediaRecorder(this._mediaStream)
                    
                    // 数据收集处理
                    this._mediaRecorder.ondataavailable = (event) => {
                        this._audioChunks.push(event.data)
                    }
                    
                    // 事件绑定
                    this._mediaRecorder.onstart = () => {
                        this._callbacks.start.forEach(cb => cb())
                    }
                    
                    this._mediaRecorder.onpause = () => {
                        this._callbacks.pause.forEach(cb => cb())
                    }
                    
                    this._mediaRecorder.onstop = () => {
                        const format = options.format || 'wav'
                        const audioBlob = new Blob(this._audioChunks, {
                            type: 'audio/' + format // 支持wav/mp3格式
                        })
                        this._callbacks.stop.forEach(cb => cb({
                            tempFilePath: URL.createObjectURL(audioBlob)
                        }))
                        this._audioChunks = []
                    }
                    
                    this._mediaRecorder.start()
                } catch (err) {
                    this._callbacks.error.forEach(cb => cb(err))
                }
            },
            
            // 停止录音
            stop() {
                if (this._mediaRecorder && this._mediaRecorder.state === 'recording') {
                    this._mediaRecorder.stop()
                    this._mediaStream.getTracks().forEach(track => track.stop())
                }
            },
            
            // 事件监听
            onStart(callback) {
                this._callbacks.start.push(callback)
            },
            
            onStop(callback) {
                this._callbacks.stop.push(callback)
            },
            
            onPause(callback) {
                this._callbacks.pause.push(callback)
            },
            
            onError(callback) {
                this._callbacks.error.push(callback)
            }
        }
        uni.getRecorderManager = () => {
            return recorderManager
        }
        // #endif
        
        // 处理rpx2px
        if (uni.rpx2px == null) {
            uni.rpx2px = rpx => {
                const systemInfo = uni.getSystemInfoSync()
                return (rpx * systemInfo.windowWidth) / 750
            }
        }
        
        // 修复loading和toast优先级
        
        let loadingOptions = null
        
        let toastOptions = null
        
        const uniShowToast = uni.showToast
        
        const uniShowLoading = uni.showLoading
        
        uni.showToast = options => {
            if (options == null) {
                options = {}
            }
            options.duration = options.duration || 1500
            toastOptions = options
            setTimeout(() => {
                if (options === toastOptions) {
                    toastOptions = null
                    if (loadingOptions) {
                        uniShowLoading({
                            title: loadingOptions.title,
                            mask: loadingOptions.mask
                        }).catch()
                    }
                }
            }, options.duration)
            return uniShowToast(options)
        }
        
        uni.showLoading = options => {
            if (options == null) {
                options = {}
            }
            if (loadingOptions) {
                if (loadingOptions.title === options.title) {
                    if (loadingOptions.mask === options.mask) {
                        return
                    }
                }
            }
            loadingOptions = options
            if (toastOptions) {
                return
            }
            uniShowLoading({
                title: options.title,
                mask: options.mask
            }).catch()
        }
        
        const uniHideLoading = uni.hideLoading
        
        uni.hideLoading = () => {
            loadingOptions = null
            if (toastOptions == null){
                uniHideLoading()
            }
        }
        
    }
}
